package org.kabanyo.components {
	import flash.events.MouseEvent;

	import spark.components.Button;
	import spark.components.SkinnableContainer;

	/**
	 * Container with zoom capability.
	 * @author Desky Natalio
	 *
	 */
	public class MeasurableContainer extends SkinnableContainer {
		public static const DEFAULT_SCALE_STEP_SIZE:Number = 0.01;
		public static const DEFAULT_MOVE_STEP_SIZE:Number = 20;

		//Skin Part
		[SkinPart(required = "false")]
		public var zoomInButton:Button;
		[SkinPart(required = "false")]
		public var zoomOutButton:Button;
		[SkinPart(required = "false")]
		public var homeButton:Button;
		[SkinPart(required = "false")]
		public var leftButton:Button;
		[SkinPart(required = "false")]
		public var rightButton:Button;
		[SkinPart(required = "false")]
		public var upButton:Button;
		[SkinPart(required = "false")]
		public var downButton:Button;

		private var dragEnabled:Boolean = false;
		private var startX:Number;
		private var startY:Number;
		private var actualScale:Number = 1;

		private var _scaleStepSize:Number = DEFAULT_SCALE_STEP_SIZE;

		[Bindable]
		public function get scaleStepSize():Number {
			return _scaleStepSize;
		}

		public function set scaleStepSize(value:Number):void {
			_scaleStepSize = value;
		}

		private var _moveStepSize:Number = DEFAULT_MOVE_STEP_SIZE;

		[Bindable]
		public function get moveStepSize():Number {
			return _moveStepSize;
		}

		public function set moveStepSize(value:Number):void {
			_moveStepSize = value;
		}

		public function MeasurableContainer() {
			super();
			addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
		}

		override protected function partAdded(partName:String, instance:Object):void {
			super.partAdded(partName, instance);
			if (instance == contentGroup) {
				contentGroup.addEventListener(MouseEvent.MOUSE_DOWN, contentGroup_mouseDownHandler);
				contentGroup.addEventListener(MouseEvent.MOUSE_UP, contentGroup_mouseUpHandler);
				contentGroup.addEventListener(MouseEvent.MOUSE_MOVE, contentGroup_mouseOverHandler);
			}
			if (instance == homeButton) {
				homeButton.addEventListener(MouseEvent.CLICK, homeButton_clickHandler);
			}
		}

		override protected function partRemoved(partName:String, instance:Object):void {
			super.partRemoved(partName, instance);
			if (instance == contentGroup) {
				contentGroup.removeEventListener(MouseEvent.MOUSE_DOWN, contentGroup_mouseDownHandler);
				contentGroup.removeEventListener(MouseEvent.MOUSE_UP, contentGroup_mouseUpHandler);
				contentGroup.removeEventListener(MouseEvent.MOUSE_MOVE, contentGroup_mouseOverHandler);
			}
			if (instance == homeButton) {
				homeButton.removeEventListener(MouseEvent.CLICK, homeButton_clickHandler);
			}
		}

		public function scaleUp():void {
			contentGroup.scaleX = contentGroup.scaleX + scaleStepSize;
			contentGroup.scaleY = contentGroup.scaleY + scaleStepSize;
		}

		public function scaleDown():void {
			contentGroup.scaleX = contentGroup.scaleX - scaleStepSize;
			contentGroup.scaleY = contentGroup.scaleY - scaleStepSize;
		}

		public function moveUp():void {
			contentGroup.y = contentGroup.y + moveStepSize;
		}

		public function moveDown():void {
			contentGroup.y = contentGroup.y - moveStepSize;
		}

		public function moveLeft():void {
			contentGroup.x = contentGroup.x + moveStepSize;
		}

		public function moveRight():void {
			contentGroup.x = contentGroup.x - moveStepSize;
		}

		public function home():void {
			var widthDelta:Number = width - contentGroup.width;
			var heightDelta:Number = height - contentGroup.height;
			var widthScale:Number = width / contentGroup.width;
			var heightScale:Number = height / contentGroup.height;
			if (widthDelta < 0 && heightDelta < 0) {
				if (widthScale >= heightScale) {
					actualScale = widthScale;
				} else {
					actualScale = heightScale;
				}
			} else if (widthDelta < 0 && heightDelta >= 0) {
				actualScale = widthScale;
			} else if (widthDelta >= 0 && heightDelta < 0) {
				actualScale = heightScale;
			} else if (widthDelta > 0 && heightDelta > 0) {
				if (widthScale <= heightScale) {
					actualScale = widthScale;
				} else {
					actualScale = heightScale;
				}
			} else {
				actualScale = 1;
			}
			actualScale = Math.floor(actualScale / scaleStepSize) * scaleStepSize;
			if (actualScale == 0) {
				actualScale = 1;
			}
			contentGroup.scaleX = actualScale;
			contentGroup.scaleY = actualScale;
			contentGroup.horizontalCenter = 0;
			contentGroup.verticalCenter = 0;
		}

		private function mouseWheelHandler(event:MouseEvent):void {
			if (event.delta >= 0) {
				scaleUp();
			} else {
				scaleDown();
			}
		}

		private function contentGroup_mouseDownHandler(event:MouseEvent):void {
			dragEnabled = true;
			contentGroup.horizontalCenter = null;
			contentGroup.verticalCenter = null;
			startX = event.stageX - contentGroup.x;
			startY = event.stageY - contentGroup.y;
		}

		private function contentGroup_mouseUpHandler(event:MouseEvent):void {
			dragEnabled = false;
		}

		private function contentGroup_mouseOverHandler(event:MouseEvent):void {
			if (dragEnabled) {
				contentGroup.x = event.stageX - startX;
				contentGroup.y = event.stageY - startY;
			}
		}

		private function homeButton_clickHandler(event:MouseEvent):void {
			home();
		}
	}
}
